#include "trancevideo.h"

TranceVideo::TranceVideo(QObject *parent) : QObject(parent)
{
    //注册组件
    av_register_all();
    this->inFormatContext = avformat_alloc_context();
        if (this->inFormatContext == nullptr) {
            qDebug() << "Failed to allocate input format context";
        }
        this->outFormatContext = avformat_alloc_context();
        if (this->outFormatContext == nullptr) {
            qDebug() << "Failed to allocate output format context";
        }
        this->pkt = (AVPacket*)malloc(sizeof(AVPacket));
        if (this->pkt == nullptr) {
            qDebug() << "Failed to allocate AVPacket";
        }
    this->videolndex=-1;

}

TranceVideo::~TranceVideo()
{

}

void TranceVideo::openH264File(QString filepath)
{
    int res=avformat_open_input(&(this->inFormatContext),filepath.toUtf8().constData(),nullptr,nullptr);
    if(res!=0)
    {
        qDebug()<<"avformat_open_input fail;";
    }
    else {
        qDebug()<<"avformat_open_input succuss";
    }
    res=avformat_find_stream_info(this->inFormatContext,nullptr);
    if(res<0)
    {
        qDebug()<<"avformat_find_stream_info fail;";
    }
    else {
        qDebug()<<"avformat_find_stream_info succuss";
    }

    //判断是否为视频流
    for(int i=0;i<this->inFormatContext->nb_streams;i++)
    {
        if(this->inFormatContext->streams[i]->codec->coder_type==AVMEDIA_TYPE_VIDEO)
        {

            this->videolndex=i;
            this->totalFrames = this->inFormatContext->streams[i]->nb_frames;
            if (this->totalFrames <= 0)
            {
                            // 如果文件中没有记录总帧数，这里可以考虑其他方法
                 qDebug() << "Total frames information not available in the file.";
            }
            else
            {
                  qDebug() << "Total frames: " << this->totalFrames;
            }
            break;
        }
    }
    if(this->videolndex==-1)
    {
        qDebug()<<"video stream bo found";
    }
    else {
        qDebug()<<"vidoelndex"<<videolndex;
    }




//    //计算总帧率
//    AVPacket packet;
//    while(!av_read_frame(inFormatContext,&packet))
//    {
//        if(packet.stream_index==videolndex)
//        {
//            totalFrames++;
//            qDebug()<<"totalFrames="<<totalFrames;
//        }
//        av_packet_unref(&packet);
//    }
//    res = av_seek_frame(inFormatContext, videolndex, 0, AVSEEK_FLAG_FRAME);
//    if (res != 0) {
//        qDebug() << "av_seek_frame failed with error:"<< res;
//    }

//    if(totalFrames==0)
//    {
//        qDebug()<<"没有";
//    }
//    else {
//        qDebug()<<"总帧数为"<<totalFrames;
//    }
    //this->setIsStop(false);
}






void TranceVideo::tranceToMp4(QString filepath)
{
    //通过文件名称猜测输出模式

    this->outputFormat=av_guess_format(nullptr,filepath.toUtf8().constData(),nullptr);
    if(this->outputFormat==nullptr)
    {
        qDebug()<<"av_guess_format fail";
    }
    else {
        qDebug()<<"av_guess_format success";
    }
    //设置格式
    this->outFormatContext->oformat=this->outputFormat;
    //打开视频流
    int res=avio_open(&(this->outFormatContext->pb),filepath.toStdString().c_str(),AVIO_FLAG_WRITE);
    if(res<0)
    {
        qDebug()<<"avio_open fail";
    }
    else {
       qDebug()<<"avio_open success";
    }
    //创建视频流
    AVStream*newStream=avformat_new_stream(this->outFormatContext,nullptr);
    if(newStream==0)
    {
        qDebug()<<"avformat_new_stream fail";
    }
    else {
       qDebug()<<"avformat_new_stream success";
    }

    //参数设置
    avcodec_parameters_copy(newStream->codecpar,this->inFormatContext->streams[this->videolndex]->codecpar);
    //默认设置
    newStream->codecpar->codec_tag=0;
    //写头帧信息
    res=avformat_write_header(this->outFormatContext,nullptr);
    if(res<0)
    {
        qDebug()<<"avformat_write_header fail";
    }
    else {
       qDebug()<<"avformat_write_header success";
    }

    //生成一个码流数据AVPacket
    int size=newStream->codecpar->width*newStream->codecpar->height;
    res=av_new_packet(pkt,size);

    if(res!=0)
    {
        qDebug()<<"av_new_packet fail";
    }
    else {
       qDebug()<<"av_new_packet success";
    }


    //循环转码 计算总帧数

    frameCount=0;
    while(av_read_frame(this->inFormatContext,this->pkt)==0)
    {
        qDebug()<<this->pkt->stream_index;
        if(this->pkt->stream_index==this->videolndex)
        {
            frameCount++;
            qDebug()<<"frameCount="<<frameCount;
            //转码核心代码
            if(this->pkt->pts==AV_NOPTS_VALUE)
            {
                AVRational timebase1=this->inFormatContext->streams[this->videolndex]->time_base;

                //计算两帧之间的时长
                int64_t duration=(double)AV_TIME_BASE/(double)av_q2d(this->inFormatContext->streams[this->videolndex]->r_frame_rate);
                this->pkt->pts=(double)(frameCount*duration)/(double)(av_q2d(timebase1)*AV_TIME_BASE);

                //解码时间基
                this->pkt->dts=this->pkt->pts;

                //时长计算
                this->pkt->duration=(double)duration/(double)(av_q2d(timebase1)*AV_TIME_BASE);

            }
            else if(this->pkt->pts<this->pkt->dts)
            {
                continue;
            }
            //解码时间基转换
            this->pkt->dts=av_rescale_q_rnd(this->pkt->dts,
                                            this->inFormatContext->streams[this->videolndex]->time_base,
                                             newStream->time_base,
                                               (AVRounding)(AV_ROUND_INF|AV_ROUND_PASS_MINMAX));

            //显示时间基转换
            this->pkt->pts=av_rescale_q_rnd(this->pkt->pts,
                                            this->inFormatContext->streams[this->videolndex]->time_base,
                                             newStream->time_base,
                                               (AVRounding)(AV_ROUND_INF|AV_ROUND_PASS_MINMAX));


            //两帧之间的时间转换
            this->pkt->duration=av_rescale_q(this->pkt->duration,
                                                this->inFormatContext->streams[this->videolndex]->time_base,
                                                newStream->time_base);

            //设置数据在流中的位置
            this->pkt->pos=1;
            //标志关键帧
            this->pkt->flags|=AV_PKT_FLAG_KEY;
            //AVPacket在stream的位置
            this->pkt->stream_index=0;

            x++;

            //写一帧
            av_interleaved_write_frame(this->outFormatContext,this->pkt);
            //发送给主线程

        }
        //重置
        av_packet_unref(this->pkt);
    }
    av_write_trailer(this->outFormatContext);

    avio_close(this->outFormatContext->pb);

    av_free(this->outFormatContext);

    avformat_close_input(&(this->inFormatContext));
    av_free(this->inFormatContext);
    qDebug()<<"转码成功";

}

int TranceVideo::getFrameCount() const
{
    return frameCount;
}

void TranceVideo::setFrameCount(int value)
{
    frameCount = value;
}

int TranceVideo::getTotalFrames() const
{
    return totalFrames;
}

void TranceVideo::setTotalFrames(int value)
{
    totalFrames = value;
}

int TranceVideo::getX() const
{
    return x;
}

void TranceVideo::setX(int value)
{
    x = value;
}




